package com.youan.log.common.threadtask;

import com.youan.log.common.bean.ValidateResult;
import com.youan.log.common.entity.ThreadTaskProgress;
import com.youan.log.common.service.IThreadTaskProgressService;
import org.apache.commons.lang3.Validate;
import org.springblade.core.tool.utils.SpringUtil;

import java.time.LocalDateTime;

/**
 * 进度任务线程抽象父类
 */
public abstract class AbsTaskThread implements Runnable {

    protected final ThreadTaskKeys taskKeys;
    protected ThreadTaskProgressor taskProgress;

    private Long taskId;
    private IThreadTaskProgressService taskLogService;

    public AbsTaskThread(ThreadTaskKeys taskKeys) {
        taskLogService = SpringUtil.getBean(IThreadTaskProgressService.class);
        Validate.notNull(taskLogService, "TaskThread必须在Spring环境下使用，并且容器中存在[IThreadTaskLogService]类型的实例");

        this.taskKeys = taskKeys;
    }

    @Override
    public void run() {
        beforeCheck();
        // 检查是否可用开始任务
        ValidateResult checkResult = taskCheck();
        // 如果检查不通过
        if(!checkResult.isPass()) {
            // 记录检查错误
            ThreadTaskProgress checkFailTask = recordCheckFailErrorLog(checkResult.getMessage());
            afterCheckFail(checkFailTask);
            return;
        }
        // 记录开始任务节点
        Long taskId = recordTaskStart();
        this.taskId = taskId;
        this.taskProgress = new ThreadTaskProgressor(taskId);
        afterCheckPass(taskId);

        // 获取任务总数
        int progressTotalNum = getTaskProgressTotal();
        this.taskProgress.updateProgressTotal(progressTotalNum);

        try {
            // 任务执行前钩子
            beforeDoTask();
            // 执行任务
            doTask();
        }catch (Exception e) {
            // 记录执行任务过程中的错误
            recordTaskError(e.getMessage());
            afterTaskFailueEnd();
            e.printStackTrace();
            return;
        }
        // 记录正确完成任务
        recordTaskSuccessEnd();
        afterSuccessEnd();
    }

    protected void afterTaskFailueEnd(){

    }

    protected void afterSuccessEnd() {
    }

    /**
     * 检查失败钩子
     * @author xsh
     * @date 2021/3/5 15:07
     * @param: checkFailTask
     * @return
     */
    protected void afterCheckFail(ThreadTaskProgress checkFailTask) {
    }

    /**
     * 检查前钩子
     * @author xsh
     * @date 2021/3/5 14:50
     * @param:
     * @return
     */
    protected void beforeCheck() {

    }

    /**
     * 通过检查后的钩子
     * @author xsh
     * @date 2021/3/4 15:27
     * @param:
     * @return
     * @param taskId
     */
    protected void afterCheckPass(Long taskId) {

    }

    /**
     * 任务执行前钩子
     */
    protected void beforeDoTask(){

    }


    /**
     * 检查是否可以开始任务 <br/>
     * 此方法中可以进行任务前检查并返回检查结果 <br/>
     * &nbsp;&nbsp;&nbsp;&nbsp;1.如果检查通过可以执行任务: canRunTask: true msg: 空  <br/>
     * &nbsp;&nbsp;&nbsp;&nbsp;2.如果检查不通过: canRunTask: false msg: 错误原因 <br/>
     * 检查不通过将会自动记录日志 <br/>
     *
     * @return
     */
    protected abstract ValidateResult taskCheck();

    /**
     * 开始具体任务
     */
    protected abstract void doTask();

    /**
     * 获取任务进度总数
     * @return
     */
    protected abstract Integer getTaskProgressTotal();

    protected Long recordTaskStart() {
        ThreadTaskProgress progress = new ThreadTaskProgress();
        progress.setTaskName(taskKeys.getThreadTaskName());
        progress.setTaskStatus(taskKeys.getStartStatusKey());
        progress.setTaskStatusText(taskKeys.getStartStatusValue());
        progress.setMessage(getStartMessage());
        progress.setStartTime(LocalDateTime.now());

        taskLogService.save(progress);

        return progress.getId();
    }

    protected String getStartMessage() {
        return "";
    }


    protected void recordTaskError(String errorMsg) {
        ThreadTaskProgress updateTask = new ThreadTaskProgress();
        updateTask.setId(this.taskId);
        updateTask.setTaskStatus(taskKeys.getErrorStatusKey());
        updateTask.setTaskStatusText(taskKeys.getErrorStatusValue());
        updateTask.setMessage(errorMsg);
        updateTask.setEndTime(LocalDateTime.now());

        taskLogService.updateById(updateTask);
    }

    /**
     * 记录任务正常完成
     */
    private void recordTaskSuccessEnd() {
        ThreadTaskProgress updateTask = new ThreadTaskProgress();
        updateTask.setId(this.taskId);
        updateTask.setTaskStatus(taskKeys.getEndStatusKey());
        updateTask.setTaskStatusText(taskKeys.getEndStatusValue());
        updateTask.setEndTime(LocalDateTime.now());
        updateTask.setTaskProgressCurrent(taskProgress.getProgressTotalNum());
        updateTask.setMessage(getSuccessEndMessage());

        taskLogService.updateById(updateTask);
    }

    protected String getSuccessEndMessage() {
        return "";
    }


    /**
     * 记录检查失败无法启动任务日志
     * @param errorMsg 错误原因
     */
    protected ThreadTaskProgress recordCheckFailErrorLog(String errorMsg) {
        ThreadTaskProgress task = new ThreadTaskProgress();
        task.setTaskName(taskKeys.getThreadTaskName());
        task.setTaskStatus(taskKeys.getErrorStatusKey());
        task.setTaskStatusText(taskKeys.getErrorStatusValue());
        task.setMessage(errorMsg);
        task.setStartTime(LocalDateTime.now());
        task.setEndTime(LocalDateTime.now());

        taskLogService.save(task);
        return task;
    }


}
